#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h> /* htonl */
#include "srvparser.h"
#include "wifi.h"
#include "data_sock.h"
#include "debug.h"

typedef enum{
  MALFORMED_CMD,
  NOTSUPPORTED_CMD
} err_code;

static ctrl_ack ctrlAck;    //Store server replies (SRV side)

static postSynchAction pSA;

static void error(err_code e);

static void error(err_code e)
{
	printf("srvparser.c : ERR_CODE %i\n",(int)e);
	return;
}

ctrl_ack *srvparser_cmd(char *cmdline){
  int i;
  char **args;
  char *ptr;
  char *cmd = malloc(CMD_SZ);
  memset(cmd,0,CMD_SZ);
  sscanf(cmdline, "%s", cmd);
  if(memcmp(cmd,"#",1)==0) return NULL;
  if(memcmp(cmdline,"\n",1)==0) return NULL;
  args = malloc(sizeof(char *) * MAX_ARGS);
  i = 0;
  ptr = cmdline + strlen(cmd); // Pointer to next token of the string.
  for(i = 0; i < MAX_ARGS; i++)
  {
    args[i] = malloc(ARG_SZ);
    memset(args[i],0,ARG_SZ);
    sscanf(ptr, "%s", args[i]);
    ptr = ptr + strlen(args[i]) + 1;
  }
  memset(&ctrlAck, 0, sizeof(ctrl_ack));
  if(memcmp("openctrl",cmd,8)==0)
  {
    ctrlAck.action=htons(OPENCTRL);
    ctrlAck.result=1;
    ctrlAck.reason=htons(REASON(OPENCTRL,OK));
  }
  if(memcmp("opendata",cmd,8)==0)
  {
    /** 
     * Here we need to check if the client wants wifi
     * and we have or we don't. If we have the result
     * of the opendata must be 1 otherwise it must
     * be 0 as we don't use a wireless interface 
     * to receive data.
     */
    
    ctrlAck.action=htons(OPENDATA);
    ctrlAck.result=1;
    ctrlAck.reason=htons(REASON(OPENDATA,OK));
    for (i=0;i<MAX_ARGS;i++)
    {
      //If the client wants wifi
      if(memcmp(args[i],"wlan",4)==0)
      {
        //and we have it
        if(wifi_getEn()==WIFIENABLED)
        {
        }
        else
        {
          //Otherwise deny the command
          ctrlAck.action=htons(OPENDATA);
          ctrlAck.result=0;
          ctrlAck.reason=htons(REASON(OPENDATA,NOWIFI));
        }
      }
    }
    if(ctrlAck.result==1) ds_open();
  }
  else if(memcmp("set",cmd,3)==0)
  {
    int err = 0;
    ctrlAck.action=htons(SET);
    sscanf(cmdline, "%*s %s %s", args[0], args[1]);
    for (i=0;i<MAX_ARGS;i++)
    {
      if(memcmp(args[i],"rate=",5)==0)
      {
        err = wifi_setRate(atof((char*)(args[i]+5)));
        if (err<0) 
        {
          ctrlAck.result=0;
          ctrlAck.reason=htons(REASON(SET,UNAV_WIFI_RATE));
        }
        else{
          ctrlAck.result=1;
          ctrlAck.reason=htons(REASON(SET,OK));
        }
      }
      else if(memcmp(args[i],"channel=",8)==0)
      {
	int ch=-1;
	/**
	 * We CANNOT switch the channel now .. otherwise TCP control reply would be
	 * sent throughout the new, wrong channel!!! Therefore we
	 * postpone the wifi_setCh function
	 */
	dbg_printf(5, "srvparser.c: \tENTERING POSTSYNC MODE\n");
	memset(&pSA, 0, sizeof(postSynchAction));
	pSA.enable=1;
	pSA.type = SETCH;
	pSA.postSynchData = malloc(sizeof(int));
	ch = atoi((char*)(args[i]+8));
	memcpy(pSA.postSynchData, &ch, sizeof(int));
	
	/**
	 * Here channels filtering should be performed, in
	 * case we do not handle some of the required 
	 * channels (i.e. 12 or 13)
	 **/
	err=0;
	
        if (err<0) 
        {
          ctrlAck.result=0;
          ctrlAck.reason=htons(REASON(SET,UNAV_WIFI_CH));
        }
        else{
          ctrlAck.result=1;
          ctrlAck.reason=htons(REASON(SET,OK));
        }
      }
    }
  }
  else if(memcmp("sleep", cmd, 5)==0)
  {
    /**
    * The idea here is that we don't really need
    * to sleep.. we can eventually dispatch the
    * sleep notification to the data listener
    * collector
    */
//     int l;
//     sscanf(cmdline, "%*s %i", &l);
//     usleep(l);
    ctrlAck.action=htons(SLEEP);
    ctrlAck.result=1;
    ctrlAck.reason=htons(REASON(SLEEP,OK));
  }
  else if(memcmp("send",cmd,4)==0)
  {
    /**
    * Again we don't need to do anything but
    * return the notification reception ack.
    * to the client
    */
    ctrlAck.action=htons(SEND);
    ctrlAck.result=1;
    ctrlAck.reason=htons(REASON(SEND,OK));
  }
  else if(memcmp("closedata",cmd,9)==0)
  {
//     dbg_printf(5, "parser.c: \tDATA CONNECTION CLOSED\n");
//     rdata_free();
//     ds_close();
    ctrlAck.action=htons(CLOSEDATA);
    ctrlAck.result=1;
    ctrlAck.reason=htons(REASON(CLOSEDATA,OK));
    if(ctrlAck.result==1) ds_close();
  }
    else if(memcmp("closectrl",cmd,9)==0)
  {
    ctrlAck.action=htons(CLOSECTRL);
    ctrlAck.result=1;
    ctrlAck.reason=htons(REASON(CLOSECTRL,OK));
  }
  else
  {
    /** 
    * Non supported command or other stuff
    */
    error(MALFORMED_CMD);
    memset(&ctrlAck, 0, sizeof(ctrl_ack));
    ctrlAck.action=htons(UNKNOWN_CMD);
    ctrlAck.result=0; //Negative!
    //No reason required.
  }	
  free(cmd);
  for(i = 0; i < MAX_ARGS; i++)
  {
          free(args[i]);
  }
  return &ctrlAck;
}

postSynchAction *srvparser_getpSA(){
  return &pSA;
}
